import axios from 'axios'
import config from './config'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/store/user'

// 创建单例实例，便于统一拦截与重试
const instance = axios.create({ ...config })

// 刷新令牌相关状态
let isRefreshing = false
let pendingQueue = [] // 存放待重试请求的resolve回调

function enqueueRequest(callback) {
    pendingQueue.push(callback)
}

function flushQueue(error, token) {
    pendingQueue.forEach((callback) => {
        try {
            callback(error, token)
        } catch (_) {}
    })
    pendingQueue = []
}

// 使用干净的 axios 实例进行刷新，避免递归触发拦截器
const refreshClient = axios.create({ ...config })

async function doRefreshToken(currentRefreshToken) {
    const resp = await refreshClient.post('/auth/refresh', { refreshToken: currentRefreshToken })
    const payload = resp?.data
    // 后端返回可能为 { code, msg, data: { token, refreshToken } } 或直接 { token, refreshToken }
    const tokens = (payload && payload.data) ? payload.data : payload
    const accessToken = tokens?.token || tokens?.accessToken || ''
    const refreshTok = tokens?.refreshToken || ''
    return { accessToken, refreshToken: refreshTok, raw: payload }
}

// 请求拦截器：注入 Authorization、Content-Type
instance.interceptors.request.use(
    (req) => {
        const userStore = useUserStore()

        // 设置 Authorization 头
        const token = userStore?.token || localStorage.getItem('token')
        if (token && !req.headers?.Authorization) {
            req.headers = req.headers || {}
            req.headers.Authorization = `Bearer ${token}`
        }

        // 设置 Content-Type（可被外部覆盖）
        const method = (req.method || 'get').toLowerCase()
        if (method !== 'get') {
            const contentType = req.contentType || req.headers?.['Content-Type'] || req.headers?.['content-type']
            if (!contentType) {
                req.headers['Content-Type'] = 'application/json'
            }
        }

        return req
    },
    (error) => Promise.reject(error)
)

// 响应拦截器：统一处理 401/403，自动刷新并重试
instance.interceptors.response.use(
    (response) => {
        // 统一返回后端业务数据，便于调用处直接使用 response.code / response.data
        return response?.data !== undefined ? response.data : response
    },
    async (error) => {
        const response = error?.response
        const originalConfig = error?.config || {}
        const status = response?.status

        // 网络错误或无响应
        if (!response) {
            return Promise.reject(error)
        }

        // 避免对刷新接口本身再次触发刷新逻辑
        const isRefreshEndpoint = typeof originalConfig?.url === 'string' && originalConfig.url.includes('/auth/refresh')
        if ((status === 401 || status === 403) && !isRefreshEndpoint) {
            // 防止重复重试
            if (originalConfig._retry) {
                return Promise.reject(error)
            }
            originalConfig._retry = true

            const userStore = useUserStore()
            const currentRefreshToken = userStore?.refreshToken || localStorage.getItem('refreshToken')

            // 无 refreshToken，直接登出并跳转登录
            if (!currentRefreshToken) {
                try { userStore?.logout?.() } catch (_) {}
                // 直接跳转到登录页，带上当前路由作为重定向
                const redirect = encodeURIComponent(location.hash.replace('#', '') || '/')
                location.hash = `#/login?redirect=${redirect}`
                return Promise.reject(error)
            }

            // 如果正在刷新，排队等待
            if (isRefreshing) {
                return new Promise((resolve, reject) => {
                    enqueueRequest((err, newToken) => {
                        if (err) return reject(err)
                        // 使用最新 token 重试原请求
                        originalConfig.headers = originalConfig.headers || {}
                        originalConfig.headers.Authorization = `Bearer ${newToken}`
                        resolve(instance(originalConfig))
                    })
                })
            }

            // 发起刷新
            isRefreshing = true
            return new Promise(async (resolve, reject) => {
                try {
                    const data = await doRefreshToken(currentRefreshToken)
                    const newAccessToken = data?.accessToken || ''
                    const newRefreshToken = data?.refreshToken || ''

                    if (!newAccessToken) {
                        throw new Error('刷新令牌成功但未返回新的访问令牌')
                    }

                    // 更新本地与 store
                    try {
                        const userStoreInner = useUserStore()
                        userStoreInner.updateTokens({ token: newAccessToken, refreshToken: newRefreshToken })
                    } catch (_) {
                        if (newAccessToken) localStorage.setItem('token', newAccessToken)
                        if (newRefreshToken) localStorage.setItem('refreshToken', newRefreshToken)
                    }

                    // 唤醒队列
                    flushQueue(null, newAccessToken)

                    // 使用新 token 重试原请求
                    originalConfig.headers = originalConfig.headers || {}
                    originalConfig.headers.Authorization = `Bearer ${newAccessToken}`
                    resolve(instance(originalConfig))
                } catch (refreshErr) {
                    // 刷新失败：清理并跳转登录
                    try { useUserStore()?.logout?.() } catch (_) {
                        localStorage.removeItem('token')
                        localStorage.removeItem('refreshToken')
                        localStorage.removeItem('userInfo')
                        localStorage.removeItem('lastRefreshDate')
                    }
                    flushQueue(refreshErr)
                    ElMessage.error('登录已过期，请重新登录')
                    const redirect = encodeURIComponent(location.hash.replace('#', '') || '/')
                    location.hash = `#/login?redirect=${redirect}`
                    reject(refreshErr)
                } finally {
                    isRefreshing = false
                }
            })
        }

        // 其他错误，统一提示后抛出
        const msg = response?.data?.msg || response?.data?.message || error.message || '请求失败'
        if (status && status >= 400) {
            ElMessage({ message: msg, type: 'error', showClose: true })
        }
        return Promise.reject(error)
    }
)

export default function request(options) {
    return instance(options)
}
